package personal.web.mvc.controller.accounting;

import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import personal.dao.support.TransactionSearchCriteria;
import personal.domain.accounting.ExternalEntity;
import personal.domain.accounting.MonthwiseCalendar;
import personal.exception.UnauthorizedAccessException;
import personal.service.accounting.ExternalEntityService;
import personal.service.accounting.IncomeExpenseService;
import personal.service.accounting.TransactionService;
import personal.web.mvc.ControllerExceptionHandler;
import personal.web.mvc.controller.AbstractCommandController;
import personal.web.mvc.io.accounting.AccountingRequestParam;


@Controller("/transaction")
public class TransactionController  extends AbstractCommandController{
	private ExternalEntityService externalEntityService;
	private IncomeExpenseService incomeExpenseService;
	private TransactionService transactionService;
	private ControllerExceptionHandler controllerExceptionHandler;

	public ExternalEntityService getExternalEntityService() {
		return externalEntityService;
	}

	@Autowired(required=false)
	public void setExternalEntityService(ExternalEntityService externalEntityService) {
		this.externalEntityService = externalEntityService;
	}

	public IncomeExpenseService getIncomeExpenseService() {
		return incomeExpenseService;
	}

	@Autowired(required=false)
	public void setIncomeExpenseService(IncomeExpenseService incomeExpenseService) {
		this.incomeExpenseService = incomeExpenseService;
	}

	public TransactionService getTransactionService() {
		return transactionService;
	}

	@Autowired(required=false)
	public void setTransactionService(TransactionService transactionService) {
		this.transactionService = transactionService;
	}

	public ControllerExceptionHandler getControllerExceptionHandler() {
		return controllerExceptionHandler;
	}

	@Autowired(required=false)
	public void setControllerExceptionHandler(ControllerExceptionHandler controllerExceptionHandler) {
		this.controllerExceptionHandler = controllerExceptionHandler;
	}
	
	@ExceptionHandler(RuntimeException.class)
	public void handleException(final RuntimeException e, final HttpServletResponse response) {
		controllerExceptionHandler.handleRuntimeException(e, response);
	}
	
	@ExceptionHandler(UnauthorizedAccessException.class)
	public void handleException(final UnauthorizedAccessException e, final HttpServletResponse response) {
		controllerExceptionHandler.handleRuntimeException(e, response);
	}
	
	@RequestMapping(value="/loadallforyear",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> loadAllForYear(@RequestBody AccountingRequestParam param, HttpServletResponse httpResponse) {
		Map<String, Object> response = getResponseMap();
		TransactionSearchCriteria criteria = new TransactionSearchCriteria();
		MonthwiseCalendar calendar = new MonthwiseCalendar();
		calendar.setYear(param.getYear());
		criteria.setCalendar(calendar);
		response.put("incomeList", transactionService.getIncomeTransactions(criteria));
		response.put("expenseList", transactionService.getExpenseTransactions(criteria));
		response.put("transferList", transactionService.getTransferTransactions(criteria));
		return response;
	}	

	@RequestMapping(value="/findexpensetxns",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> findExpenseTransactions(@RequestBody AccountingRequestParam param, 
																			HttpServletResponse httpResponse) {
		Map<String, Object> response = getResponseMap();
		response.put("txns", transactionService.getExpenseTransactions(param.getCriteria()));
		return response;
	}	

	@RequestMapping(value="/findincometxns",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> findIncomeTransactions(@RequestBody AccountingRequestParam param, 
																		HttpServletResponse httpResponse) {
		Map<String, Object> response = getResponseMap();
		response.put("txns", transactionService.getIncomeTransactions(param.getCriteria()));
		return response;
	}	

	@RequestMapping(value="/findtransfertxns",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> findTransferTransactions(@RequestBody AccountingRequestParam param, 
																		HttpServletResponse httpResponse) {
		Map<String, Object> response = getResponseMap();
		response.put("txns", transactionService.getTransferTransactions(param.getCriteria()));
		return response;
	}	
	
	@RequestMapping(value="/addexpense",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> addExpenseTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		if (param.getExpenseTransaction().getEntity() != null) {
			ExternalEntity entity = param.getExpenseTransaction().getEntity();
			if (entity.getIeCategory() != null) {
				entity.setIeCategoryId(incomeExpenseService.saveIncomeExpenseCategory(entity.getIeCategory()).getCategoryId());
			}
			param.getExpenseTransaction().setEntityId(externalEntityService.saveExternalEntity(entity).getEntityId());
		}
		
		transactionService.addExpenseTransaction(param.getExpenseTransaction());
		return getResponseMap();
	}
		
	@RequestMapping(value="/adjustexpense",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> adjustExpenseTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		transactionService.adjustExpenseTransaction(param.getExpenseTransaction());
		return getResponseMap();
	}
	
	@RequestMapping(value="/deleteexpense",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> deleteExpenseTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		transactionService.deleteExpenseTransaction(param.getExpenseTransaction());
		return getResponseMap();
	}
	
	@RequestMapping(value="/addincome",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> addIncomeTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		if (param.getIncomeTransaction().getEntity() != null) {
			ExternalEntity entity = param.getIncomeTransaction().getEntity();
			if (entity.getIeCategory() != null) {
				entity.setIeCategoryId(incomeExpenseService.saveIncomeExpenseCategory(entity.getIeCategory()).getCategoryId());
			}
			param.getIncomeTransaction().setEntityId(externalEntityService.saveExternalEntity(entity).getEntityId());
		}
		
		transactionService.addIncomeTransaction(param.getIncomeTransaction());
		return getResponseMap();
	}
	
	@RequestMapping(value="/adjustincome",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> adjustIncomeTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		transactionService.adjustIncomeTransaction(param.getIncomeTransaction());
		return getResponseMap();
	}
	
	@RequestMapping(value="/deleteincome",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> deleteIncomeTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		transactionService.deleteIncomeTransaction(param.getIncomeTransaction());
		return getResponseMap();
	}
	
	@RequestMapping(value="/addtransfer",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> addTransferTransaction(@RequestBody AccountingRequestParam param,
																				HttpServletResponse httpResponse) {
		transactionService.addTransferTransaction(param.getTransferTransaction());
		return getResponseMap();
	}
	
	
	@RequestMapping(value="/adjusttransfer",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> adjustTransferTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		transactionService.adjustTransferTransaction(param.getTransferTransaction());
		return getResponseMap();
	}
	
	@RequestMapping(value="/deletetransfer",method=RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> deleteTransferTransaction(@RequestBody AccountingRequestParam param,
																					HttpServletResponse httpResponse) {
		transactionService.deleteTransferTransaction(param.getTransferTransaction());
		return getResponseMap();
	}
}
